import Taro from '@tarojs/taro'
import _isUndefined from 'lodash/isUndefined'
import _findIndex from 'lodash/findIndex'
import _debounce from 'lodash/debounce'
import classNames from 'classnames'
import { View } from '@tarojs/components'
import AtFloatLaout from '../float-layout'
import AtTimeLine from '../timeline'
import AtListItem from '../list-item/index'
import AtIndexes from '../indexes'
import AtEmpty from '../empty/index'
import { PropsType } from './PropsType'

// const hintText = ['请选择城市', '请选择县', '请选择街道']
export default class AddressSelector extends Taro.Component<PropsType, any> {
  static options = { addGlobalClass: true }
  private scrollIntoView
  private isNoDataClose = false // 是否因为无地址数据关闭
  private isLoading = false
  private isFirstLoad = true // 是否第一次获取数据
  private showEmpty = false
  static defaultProps = {
    prefixCls: 'at-address-selector',
    className: '',
    customStyle: {},
    label: '',
    defaultValue: [],
    placeholder: '请选择',
    maskClosable: true,
    showCharacterIndexes: true,
    hintList: [],
    title: '请选择',
    required: false,
    propsEmpty: {
      size: 'small',
      description: '什么都没有'
    },
    placeholderAlign: 'right'
  }

  constructor(props) {
    super(props)
    this.state = {
      _visible: false,
      _value: props.defaultValue,
      data: []
    }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.defaultValue !== nextProps.defaultValue) {
      this.setState({
        _value: nextProps.defaultValue
      })
      this.isNoDataClose = false
      this.isFirstLoad = true
      const { onChange } = this.props
      onChange(nextProps.defaultValue)
    }
  }

  componentDidUpdate() {
    const selectedValue = this.state._value.find(item => item.selected)
    if (this.state.data.length > 0) {
      if (!selectedValue || selectedValue.key === '') {
        this.scrollIntoView('SCROLLTOTOP')
      } else {
        this.scrollIntoView(null, selectedValue.key)
      }
    }
  }

  formatDataList(data) {
    data = JSON.parse(JSON.stringify(data))
    const selectedItem = this.state._value.find(item => item.selected)
    const selectedKey = selectedItem ? selectedItem.key : ''
    data.forEach(item1 => {
      item1.items.forEach(item2 => {
        if (selectedKey && item2.key === selectedKey) {
          item2.selected = true
        } else {
          item2.selected = false
        }
      })
    })
    this.setState({
      data
    })
  }

  formatValue(value, selectedKey?: string | number, data?: Array<any>) {
    value = JSON.parse(JSON.stringify(value))
    if (_isUndefined(selectedKey)) {
      // 插入提示语，如果因为无数据关闭，就不添加提示
      if (
        value.length > 0 &&
        data &&
        data.length > 0 &&
        _findIndex(value, { key: '' }) === -1 &&
        !this.isNoDataClose
      ) {
        value.push({
          name: this.props.hintList ? this.props.hintList[value.length] || '请选择' : '请选择',
          key: '',
          selected: !selectedKey && true
        })
      } else if (value.length > 0) {
        // 默认选中最后一个
        value[value.length - 1].selected = true
      }
    }
    this.setState(
      {
        _value: value
      },
      () => {
        data && this.formatDataList(data)
      }
    )
  }

  loadData(value) {
    const _value = value.filter(item => item.key !== '')
    const selectedIndex = _findIndex(_value, { selected: true })
    // isNoDataClose 如果是无数据关闭，判断是否最后一个是空key，是的话取倒数一个地址信息，不是的话取倒数第二个信息
    const dataItem =
      selectedIndex === -1
        ? this.isNoDataClose && _findIndex(value, { key: '' }) === -1
          ? _value[_value.length - 2]
          : _value[_value.length - 1]
        : _value[selectedIndex - 1]
    const selectedKey = selectedIndex === -1 ? undefined : _value[selectedIndex]
    this.isLoading = true
    this.props.onLoadData(dataItem).then(data => {
      // 第一次打开，如果最后一个value没有获取data，就要获取倒数第二个
      if (this.isFirstLoad && data.length === 0) {
        this.isFirstLoad = false
        this.isNoDataClose = true
        this.loadData(value)
        return
      }
      this.isFirstLoad = false
      // 如果获取数据为空，关闭弹窗
      if (this.state.data.length !== 0 && data.length === 0) {
        this.isNoDataClose = true
        this.showEmpty = true
        // 自己控制visible不自动关闭
        if (!this.props.hasOwnProperty('visible')) {
          this.handleClose()
        }
      }
      this.formatValue(value, selectedKey, data)
      _debounce(() => {
        this.isLoading = false
      }, 300)()
    })
  }

  handleValueItemClick = itemValue => {
    if (itemValue.disabled || this.isLoading) {
      return
    }
    let value = [...this.state._value]
    value = value.map(item1 => {
      if (item1.key === itemValue.key) {
        item1.selected = true
      } else {
        item1.selected = false
      }
      return item1
    })
    this.loadData(value)
  }

  handleDataItemClick = itemValue => {
    if (this.isLoading) {
      return
    }
    const { onChange } = this.props
    let value = [...this.state._value]
    let selectedIndex = _findIndex(value, { selected: true })
    value = value.splice(0, selectedIndex === -1 ? 0 : selectedIndex) // 删除最后一个插入最新的
    value[value.length] = { ...itemValue, selected: false }
    this.isNoDataClose = false
    onChange(value)
    this.loadData(value)
  }

  handleSelectorClick = () => {
    const { onClick } = this.props
    if (!this.props.hasOwnProperty('visible')) {
      this.setState({
        _visible: true
      })
    }
    let value = [...this.state._value]
    value.forEach(item => {
      item.selected = false
    })
    this.showEmpty = false
    this.loadData(value)
    onClick && onClick()
  }

  handleClose = () => {
    const { onClose } = this.props
    if (!this.props.hasOwnProperty('visible')) {
      this.setState({
        _visible: false
      })
    }
    onClose && onClose()
  }

  render() {
    const {
      prefixCls,
      className,
      customStyle,
      label,
      placeholder,
      showCharacterIndexes,
      title,
      maskClosable,
      visible,
      required,
      propsEmpty = {},
      placeholderAlign
    } = this.props
    const { _visible, data, _value } = this.state
    let addressText = ''
    const valueList = _value.map(item => {
      item.key && (addressText += `${item.name} `)
      return {
        ...item,
        title: item.name,
        color: item.disabled ? 'disabled' : '',
        icon: item.key === '' && 'none'
      }
    })
    const _propsEmpty = {
      ...propsEmpty,
      visible: propsEmpty.visible === undefined ? this.showEmpty : propsEmpty.visible
    }
    return (
      <View className={classNames(prefixCls, className)} style={customStyle}>
        <AtFloatLaout
          visible={this.props.hasOwnProperty('visible') ? visible : _visible}
          title={title}
          onClose={this.handleClose}
          maskClosable={maskClosable}
        >
          {_value.length !== 0 && (
            <AtTimeLine data={valueList} onClick={this.handleValueItemClick}></AtTimeLine>
          )}
          <View className={`${prefixCls}-indexes-content`}>
            {data.length > 0 ? (
              <AtIndexes
                toast={false}
                list={data}
                vibrate={false}
                onScrollIntoView={fn => {
                  this.scrollIntoView = fn
                }}
                top='Top'
                showCharacterIndexes={showCharacterIndexes}
                onClick={this.handleDataItemClick}
              ></AtIndexes>
            ) : (
              <AtEmpty {..._propsEmpty} className={`${prefixCls}-empty`}></AtEmpty>
            )}
          </View>
        </AtFloatLaout>
        {!label ? (
          <View onClick={this.handleSelectorClick}>{this.props.children}</View>
        ) : (
          <AtListItem
            onClick={this.handleSelectorClick}
            className={className}
            style={customStyle}
            align='top'
            arrow='right'
            textAlign={placeholderAlign}
            label={label}
            brief={addressText}
            required={required}
          >
            {placeholder}
          </AtListItem>
        )}
      </View>
    )
  }
}
